package TrackController;

import java.util.*;
import Utilities.*;
import application.*;
import TrackModel.*;

@SuppressWarnings("unused")
public class TrackController implements CTCOfficeToTrackController, TrackController_UI
{
	public MapElement mapElement;
	
	public int trackControllerID;
	public int controllerSize;
	public ArrayList<Block> blockRange;
	public boolean blockHealth;
	
	public int switchBlockIndex;
	public SwitchBlock switchBlock;
	public boolean switchStateNatural = false;
	public boolean hasRailwayCrossing = false;
	public CrossingBlock railwayCrossingBlock;
	public boolean railwayCrossingActivated = false;
	public boolean railwayCrossingGateActivated = false;
	public boolean railwayCrossingLightActivated = false;
	public boolean[] stations;

	private int mcmd;
	private int mtrackControllerID;
	private int mtrainID;
	private int mnatural;
	private double mspeed;
	private double mauthority;

	private String strackModelString;
	private Queue<Message> mtrackModelMessage;

	// Track controller constructor
	public TrackController(int tcid, ArrayList<Block> range)
	{
		Main.registerTrackController(this);
		mtrackModelMessage = new LinkedList<Message>();

		trackControllerID = tcid;
		controllerSize = range.size();
		

		// Set block range
		blockRange = new ArrayList<Block>(controllerSize);

		for (int i = 0; i < controllerSize; i++)
		{
			blockRange.add(i, range.get(i));
		}

		// Set switch block
		for (int i = 0; i < controllerSize; i++)
		{
			if (blockRange.get(i) instanceof SwitchBlock)
			{
				switchBlock = (SwitchBlock)blockRange.get(i);
				switchBlockIndex = i;
			}
		}

		// Set railway crossing block
		for (int i = 0; i < controllerSize; i++)
		{
			if (blockRange.get(i) instanceof CrossingBlock)
			{
				hasRailwayCrossing = true;
				railwayCrossingBlock = (CrossingBlock)blockRange.get(i);
			}
		}

		// Set station blocks
		stations = new boolean[controllerSize];

		for (int i = 0; i < controllerSize; i++)
		{
			if (blockRange.get(i) instanceof StationBlock)
			{
				stations[i] = true;
			}

			else
			{
				stations[i] = false;
			}
		}
	}

	// Tick method
	public void tick()
	{
		// Send messages to the track model
		for(String m : Main.office.messages)
		{
			this.sendMessage(m);
		}
	}
	
	// Activate railway crossing
	public void activateRailwayCrossing()
	{
		if (this.getTrainPresence().equals("YES") && !railwayCrossingActivated)
		{
			railwayCrossingBlock.toggleCrossing();
			railwayCrossingActivated = true;
			railwayCrossingGateActivated = true;
			railwayCrossingLightActivated = true;
		}
		
		else if (this.getTrainPresence().equals("NO") && railwayCrossingActivated)
		{
			railwayCrossingBlock.toggleCrossing();
			railwayCrossingActivated = false;
			railwayCrossingGateActivated = false;
			railwayCrossingLightActivated = false;
		}
		
	}
	
	// Set switch route
	public void setSwitchRoute (boolean beNatural)
	{
		for (int i = 0; i < controllerSize; i++)
		{
			if (switchStateNatural != beNatural)
			{
				switchBlock.toggleSwitch();
				switchStateNatural = !switchStateNatural;
			}
		}
	}
	
	// Check for broken track
	public boolean checkForBrokenTrack()
	{
		for (int i = 0; i < controllerSize; i++)
		{
			if (!blockRange.get(i).isHealthy())
			{
				return true;
			}
		}
		
		return false;
	}
	
	// Interpret message from CTC
	public void sendMessage(String s)
	{
		String input;

		input = s.substring(0,1);
		mcmd = Integer.parseInt(input);
		input = s.substring(1,3);

		if (mcmd == 0)
		{
			mtrackControllerID = Integer.parseInt(input);
			input = s.substring(3);
			mnatural = Integer.parseInt(input);
		}

		else
		{
			mtrainID = Integer.parseInt(input);
			input = s.substring(3);
			if (mcmd == 1)
			{
				mspeed = Double.parseDouble(input);
				strackModelString = "T " + s.substring(1,3) + " | " + "S " + s.substring(3);
				mtrackModelMessage.add(new Message(strackModelString));
			}
			else
			{
				mauthority = Double.parseDouble(input);
				strackModelString = "T " + s.substring(1,3) + " | " + "A " + s.substring(3);
				mtrackModelMessage.add(new Message(strackModelString));
			}
		}
	}
	
	// Get latest message w/o dequeuing
	public Queue<Message> getMessages()
	{
		Queue<Message> tempMessage = mtrackModelMessage;
		return tempMessage;
	}
	
	// Get and dequeue latest message
	public Message getNextMessage()
	{
		if (!mtrackModelMessage.isEmpty())
			return mtrackModelMessage.poll();
		else
			return null;
	}
	
	// Get track controller ID
	public int getTrackControllerID()
	{
		return this.trackControllerID;
	}
	
	// Get switch state
	public String getSwitchState()
	{
		if (this.switchStateNatural)
		{
			return "NATURAL";
		}
		
		return "UNNATURAL";
	}
	
	// Get crossing state
	public String getCrossingState()
	{
		if (this.hasRailwayCrossing)
		{
			return "N/A";
		}
		
		else if (this.railwayCrossingActivated)
		{
			return "ACTIVATED";
		}
		
		return "DEACTIVATED";
	}
	
	// Get crossing gate state
	public String getCrossingGateState()
	{
		if (this.hasRailwayCrossing)
		{
			return "N/A";
		}
		
		else if (this.railwayCrossingGateActivated)
		{
			return "CLOSED";
		}
		
		return "OPEN";
	}
	
	// Get crossing light state
	public String getCrossingLightState()
	{
		if (this.hasRailwayCrossing)
		{
			return "N/A";
		}
		
		else if (this.railwayCrossingLightActivated)
		{
			return "RED";
		}
		
		return "GREEN";
	}

	// Get track health
	public String getTrackHealth()
	{
		if (this.checkForBrokenTrack())
		{
			return "BROKEN";
		}
		
		return "HEALTHY";
	}

	// Get train presence
	public String getTrainPresence()
	{
		for (int i = 0; i < controllerSize; i++)
		{
			if (blockRange.get(i).hasTrain)
			{
				return "YES";
			}
		}
		
		return "NO";
	}

}
